/*
 * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package com.sun.corba.se.impl.ior;

import java.util.Iterator;

import org.omg.CORBA_2_3.portable.InputStream;
import org.omg.CORBA_2_3.portable.OutputStream;

import com.sun.corba.se.spi.protocol.CorbaServerRequestDispatcher;

import com.sun.corba.se.spi.ior.ObjectId;
import com.sun.corba.se.spi.ior.ObjectAdapterId;
import com.sun.corba.se.spi.ior.ObjectKeyTemplate;

import com.sun.corba.se.spi.orb.ORB;
import com.sun.corba.se.spi.orb.ORBVersion;

import com.sun.corba.se.spi.logging.CORBALogDomains;

import com.sun.corba.se.impl.encoding.EncapsOutputStream;

import com.sun.corba.se.impl.logging.IORSystemException;

/**
 * @author
 */
public abstract class ObjectKeyTemplateBase implements ObjectKeyTemplate {
    // Fixed constants for Java IDL object key template forms
    public static final String JIDL_ORB_ID = "";
    private static final String[] JIDL_OAID_STRINGS = { "TransientObjectAdapter" };
    public static final ObjectAdapterId JIDL_OAID = new ObjectAdapterIdArray(JIDL_OAID_STRINGS);

    private ORB orb;
    protected IORSystemException wrapper;
    private ORBVersion version;
    private int magic;
    private int scid;
    private int serverid;
    private String orbid;
    private ObjectAdapterId oaid;

    private byte[] adapterId;

    public byte[] getAdapterId() {
        return (byte[]) (adapterId.clone());
    }

    private byte[] computeAdapterId() {
        // write out serverid, orbid, oaid
        ByteBuffer buff = new ByteBuffer();

        buff.append(getServerId());
        buff.append(orbid);

        buff.append(oaid.getNumLevels());
        Iterator iter = oaid.iterator();
        while (iter.hasNext()) {
            String comp = (String) (iter.next());
            buff.append(comp);
        }

        buff.trimToSize();

        return buff.toArray();
    }

    public ObjectKeyTemplateBase(ORB orb, int magic, int scid, int serverid, String orbid, ObjectAdapterId oaid) {
        this.orb = orb;
        this.wrapper = IORSystemException.get(orb, CORBALogDomains.OA_IOR);
        this.magic = magic;
        this.scid = scid;
        this.serverid = serverid;
        this.orbid = orbid;
        this.oaid = oaid;

        adapterId = computeAdapterId();
    }

    public boolean equals(Object obj) {
        if (!(obj instanceof ObjectKeyTemplateBase))
            return false;

        ObjectKeyTemplateBase other = (ObjectKeyTemplateBase) obj;

        return (magic == other.magic) && (scid == other.scid) && (serverid == other.serverid) && (version.equals(other.version) && orbid.equals(other.orbid) && oaid.equals(other.oaid));
    }

    public int hashCode() {
        int result = 17;
        result = 37 * result + magic;
        result = 37 * result + scid;
        result = 37 * result + serverid;
        result = 37 * result + version.hashCode();
        result = 37 * result + orbid.hashCode();
        result = 37 * result + oaid.hashCode();
        return result;
    }

    public int getSubcontractId() {
        return scid;
    }

    public int getServerId() {
        return serverid;
    }

    public String getORBId() {
        return orbid;
    }

    public ObjectAdapterId getObjectAdapterId() {
        return oaid;
    }

    public void write(ObjectId objectId, OutputStream os) {
        writeTemplate(os);
        objectId.write(os);
    }

    public void write(OutputStream os) {
        writeTemplate(os);
    }

    abstract protected void writeTemplate(OutputStream os);

    protected int getMagic() {
        return magic;
    }

    // All subclasses should set the version in their constructors.
    // Public so it can be used in a white-box test.
    public void setORBVersion(ORBVersion version) {
        this.version = version;
    }

    public ORBVersion getORBVersion() {
        return version;
    }

    protected byte[] readObjectKey(InputStream is) {
        int len = is.read_long();
        byte[] result = new byte[len];
        is.read_octet_array(result, 0, len);
        return result;
    }

    public CorbaServerRequestDispatcher getServerRequestDispatcher(ORB orb, ObjectId id) {
        return orb.getRequestDispatcherRegistry().getServerRequestDispatcher(scid);
    }
}
